//
//  Parser.h
//  Solver
//
//  Created by Nicolas Winkler on 14.07.13.
//  Copyright (c) 2013 Nicolas Winkler. All rights reserved.
//

#ifndef _SOLVER_PARSER_H
#define _SOLVER_PARSER_H

#include <string>
#include <vector>
#include <stack>

#include "Exception.h"

namespace solver
{
	class Parser;
	class ParserException;

	class Tokenizer;
	class Expression;

	class TokenBlock;
	class StringTokenBlock;

	struct Operation;
	class TermTokenBlock;
	class FunctionTokenBlock;
}


/**
 * \brief used to process the syntactic structure
 */
class solver::Parser
{
private:
	unsigned int index;
	const Tokenizer* tokenizer;
	static std::string operators[];
public:
					Parser(const Tokenizer&);
					~Parser(void);

	void 			run(void);

private:
	TermTokenBlock* createTokenBlock(int beginIndex, int endIndex);

	int				findMatchingParanthesis(int startIndex) const;

	static bool 	isNumeric(const std::string& token);
	static bool 	isOperator(const std::string& token);
};


/**
 * \brief used to throw exceptions during the parsing process
 */
class solver::ParserException: public Exception
{
private:
public:
	ParserException(const std::string&);
};


/**
 * \brief base class for token blocks used during the parsing process
 */
class solver::TokenBlock
{
public:
						TokenBlock(void);
	virtual 			~TokenBlock(void);

	virtual std::string	toString(void) const = 0;
};


class solver::StringTokenBlock :
		public TokenBlock
{
	std::string token;
public:
						StringTokenBlock(const std::string& token);

	const std::string& 	getToken(void) const;

	std::string 		toString(void) const;
};


struct solver::Operation
{
	std::string operatorToken;
	const TokenBlock* operand;

	Operation(const std::string& op, const TokenBlock* operand);
};


/**
 * \brief a term
 */
class solver::TermTokenBlock :
		public TokenBlock
{
protected:
	std::vector<Operation> operations;
public:
	TermTokenBlock(void);
	TermTokenBlock(const std::vector<Operation>&);

	void 				addBlock(const std::string& op, const TokenBlock* operand);
	unsigned int 		getNOperations(void) const;
	const Operation& 	getOperation(unsigned int index) const;

	std::string 		toString(void) const;

	virtual Expression*	createExpression(void) const;
};


class solver::FunctionTokenBlock :
		public TokenBlock
{
protected:
	std::string functionName;
	std::vector<TokenBlock*> arguments;
public:
	FunctionTokenBlock(void);
	std::string 		toString(void) const;

	virtual Expression*	createExpression(void) const;
};

#endif // _SOLVER_PARSER_H
